package com.lxt.controller;

import com.lxt.common.HttpResult;
import com.lxt.common.util.CookieUtils;
import com.lxt.common.util.JsonUtils;
import com.lxt.common.util.MD5Utils;
import com.lxt.common.util.RedisOperator;
import com.lxt.pojo.BO.ShopCartBO;
import com.lxt.pojo.BO.UserBO;
import com.lxt.pojo.Users;
import com.lxt.pojo.VO.UsersVO;
import com.lxt.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author IvXuTao
 * @Package com.lxt.controller
 * @date 2022/4/21 16:40
 */
@RestController
@RequestMapping("/passport")
@Api(value = "注册登录", tags = {"用于注册登录的相关接口"})
public class PassportController extends BaseController {

    @Autowired
    private UserService userService;
    @Autowired
    private RedisOperator redisOperator;

    @ApiOperation(value = "用户名是否存在", notes = "用户名是否存在", httpMethod = "GET")
    @GetMapping("/userNameIsExist")
    public HttpResult queryNameIsExist(@RequestParam String username) {

        //1.判断用户名不能为空
        if (StringUtils.isBlank(username)) {
            return HttpResult.errorMsg("用户名不能为空");
        }

        // 2.查找注册的用户名是否存在
        boolean isExist = userService.queryNameIsExist(username);
        if (isExist) {
            return HttpResult.errorMsg("用户名已存在");
        }

        // 3.请求成功，用户名没有重复
        return HttpResult.ok();
    }


    @ApiOperation(value = "用户注册", notes = "用户注册", httpMethod = "POST")
    @PostMapping("/register")
    public HttpResult register(@RequestBody UserBO userBO,
                               HttpServletRequest request, HttpServletResponse response) {

        String username = userBO.getUsername();
        String password = userBO.getPassword();
        String confirmPwd = userBO.getConfirmPassword();

        //1.判断用户名和密码不为空
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password) || StringUtils.isBlank(confirmPwd)) {
            return HttpResult.errorMsg("用户名或密码不能为空");
        }
        //2.查找注册的用户名是否存在
        boolean isExist = userService.queryNameIsExist(username);
        if (isExist) {
            return HttpResult.errorMsg("用户名已存在");
        }
        //3.密码长度不能小于6位
        if (password.length() <= 5) {
            return HttpResult.errorMsg("密码长度不能小于6位");
        }
        //4.判断两次密码是否一致
        if (!password.equals(confirmPwd)) {
            return HttpResult.errorMsg("两次输入的密码不一致");
        }
        //5.实现注册
        Users user = userService.createUser(userBO);

        //user = setNullProperty(user);

        // 实现用户的redis会话
        UsersVO usersVO = conventUsersVO(user);

        //设置cookie信息
        CookieUtils.setCookie(request, response, "user",
                //isEncode为是否加密
                JsonUtils.objectToJson(usersVO), true);

        //同步购物车数据
        syncShopCartData(user.getId(), request, response);
        //6.请求成功，用户名没有重复
        return HttpResult.ok(user);
    }


    @ApiOperation(value = "用户登录", notes = "用户登录", httpMethod = "POST")
    @PostMapping("/login")
    public HttpResult login(@RequestBody UserBO userBO,
                            HttpServletRequest request, HttpServletResponse response) throws Exception {

        String username = userBO.getUsername();
        String password = userBO.getPassword();

        //1.判断用户名和密码不为空
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            return HttpResult.errorMsg("用户名或密码不能为空");
        }

        //2.实现登陆查询
        Users user = userService.queryUserForLogin(username,
                //数据库存储的是加密后的密码，所以需要进行加密后比较
                MD5Utils.getMD5Str24(password));

        if (user == null) {
            return HttpResult.errorMsg("用户名或密码不正确");
        }

        //user = setNullProperty(user);
        // 实现用户的redis会话
        UsersVO usersVO = conventUsersVO(user);

        //设置cookie信息
        CookieUtils.setCookie(request, response, "user",
                //isEncode为是否加密
                JsonUtils.objectToJson(usersVO), true);

        //同步购物车数据
        syncShopCartData(user.getId(), request, response);

        //3.请求成功
        return HttpResult.ok(user);
    }

    /**
     * 注册登录成功后，同步cookie和redis中的购物车数据
     */
    private void syncShopCartData(String userId, HttpServletRequest request, HttpServletResponse response) {

        /**
         * 1.redis中无数据，如果cookie中的购物车为空，这个时候不做任何处理
         *                如果cookie中的购物车不为空，直接同步
         *
         * 2.redis中有数据，如果cookie中的购物车为空，直接把redis的购物车覆盖本地cookie
         *                如果cookie中的购物车不为空，
         *                      如果cookie某个商品在redis中存在，
         *                      以cookie为主，删除cookie中的商品直接覆盖redis中的数据(参考京东)
         *
         * 3.同步到redis中以后，覆盖本地cookie购物车的数据，保证本地购物车中的数据是同步最新的
         */

        //从redis中获取购物车
        String shopCartJsonRedis = redisOperator.get(FOODIE_SHOP_CART + ":" + userId);

        //从cookie中获取购物车
        String shopCartStrCookie = CookieUtils.getCookieValue(request, FOODIE_SHOP_CART, true);

        if (StringUtils.isBlank(shopCartJsonRedis)) {
            //redis为空,cookie不为空,直接把cookie中的数据放入redis
            if (StringUtils.isNotBlank(shopCartStrCookie)) {
                redisOperator.set(FOODIE_SHOP_CART + ":" + userId, shopCartStrCookie);
            }
        } else {
            // redis不为空，cookie不为空，合并cookie和redis中购物车的商品数据(同一商品则覆盖redis)
            if (StringUtils.isNotBlank(shopCartStrCookie)) {
                /**
                 * 1.已经存在的，把cookie中对应的数量，覆盖redis(参考京东)
                 * 2.该项商品标记为待删除，统一放入一个待删除的list
                 * 3.从cookie清理所有的待删除list
                 * 4.合并redis和cookie中的数据
                 * 5.更新到redis和cookie中
                 */
                List<ShopCartBO> shopCartListRedis = JsonUtils.jsonToList(shopCartJsonRedis, ShopCartBO.class);
                List<ShopCartBO> shopCartListCookie = JsonUtils.jsonToList(shopCartStrCookie, ShopCartBO.class);
                //定义一个待删除List
                List<ShopCartBO> pendingDeleteList = new ArrayList<>();

                for (ShopCartBO redisShopCart : shopCartListRedis) {
                    String redisSpecId = redisShopCart.getSpecId();

                    for (ShopCartBO cookieShopCart : shopCartListCookie) {
                        String cookieSpecId = cookieShopCart.getSpecId();

                        if (redisSpecId.equals(cookieSpecId)) {
                            //覆盖购买数量，不累加，参考京东
                            redisShopCart.setBuyCounts(cookieShopCart.getBuyCounts());
                            //把cookieShopCart放入待删除列表，用于最后的删除与合并
                            pendingDeleteList.add(cookieShopCart);
                        }
                    }
                }
                //从现有cookie中删除对应的覆盖过的商品数据
                shopCartListCookie.removeAll(pendingDeleteList);

                //合并两个list
                shopCartListRedis.addAll(shopCartListCookie);

                //更新到redis和cookie
                CookieUtils.setCookie(request, response, FOODIE_SHOP_CART, JsonUtils.objectToJson(shopCartListRedis), true);
                redisOperator.set(FOODIE_SHOP_CART + ":" + userId, JsonUtils.objectToJson(shopCartListRedis));

            } else {
                // redis不为空，cookie为空，直接把redis覆盖cookie
//                if (StringUtils.isNotBlank(shopCartJsonRedis)) {
//                    if (StringUtils.isBlank(shopCartStrCookie)) {
//                   }
//                }
                CookieUtils.setCookie(request, response, FOODIE_SHOP_CART, shopCartJsonRedis, true);
            }
        }
    }

    private Users setNullProperty(Users user) {
        user.setPassword(null);
        user.setRealname(null);
        user.setEmail(null);
        user.setCreatedTime(null);
        user.setUpdatedTime(null);
        user.setBirthday(null);
        return user;
    }

    @ApiOperation(value = "退出登录", notes = "退出登录", httpMethod = "POST")
    @PostMapping("/logout")
    public HttpResult logout(@RequestParam String userId,
                             HttpServletRequest request, HttpServletResponse response) {
        //清除用户的相关的信息cookie
        CookieUtils.deleteCookie(request, response, "user");

        //用户退出登录，清除redis中user的会话信息
        redisOperator.del(REDIS_USER_TOKEN + ":" + userId);

        //分布式会话中需要清除用户数据
        CookieUtils.deleteCookie(request, response, FOODIE_SHOP_CART);

        return HttpResult.ok();
    }
}
